using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;

using KmlUtils;

namespace StormModelToKMLDB
{
    public enum Category
    {
        TD = 1,
        TS = 2,
        Cat1 = 3,
        Cat2 = 4,
        Cat3 = 5,
        Cat4 = 6,
        Cat5 = 7
    }
    public class Storm : IKml
    {
        #region Private Members
        int[] hrs = new int[]{0,12,24,36,48,72,96,120};
        string _name;
        string _stormID;
        string _desc;
        DateTime _dateTime;
        Observation _initial;
        List<ICoordinate> _trackHistory;
        Dictionary<string, Buoy> _buoys;
        List<Radar> _radars;
        List<NHCDiscussion> _nhcDiscussions = new List<NHCDiscussion>();
        string _buoyImgHref;
        #endregion

        #region Public Methods / Properties
        public List<NHCDiscussion> NhcDiscussions
        {
            get { return _nhcDiscussions; }
            set { _nhcDiscussions = value; }
        }
        public string BuoyImgHref
        {
            get { return _buoyImgHref; }
            set { _buoyImgHref = value; }
        }
        public List<Radar> Radars
        {
            get { return _radars; }
            set { _radars = value; }
        }
        public Dictionary<string, Buoy> Buoys
        {
            get { return _buoys; }
            set { _buoys = value; }
        }
        public static List<Storm> ParseNHC(byte[] b)
        {
            List<Storm> storms = new List<Storm>();

            // Create an ASCII reader from the byte array
            StringReader r = new StringReader(Encoding.ASCII.GetString(b));

            // state 0 = before beg of storm
            // state 1 = inside single storm
            // state 2 = end of storm
            int state = 0;
            String line = "";
            StringBuilder buf = new StringBuilder();
            while ((line = r.ReadLine()) != null)
            {
                // Beginning of a storm
                if (line.IndexOf("CHGHUR") > -1)
                    state = 1;

                // End of a storm
                if (state == 1 && line.Contains("RD34NE"))
                {
                    buf.Append(line.Trim());
                    // Reset State for a possible new storm
                    state = 0;
                    string single = buf.ToString();

                    // Create an add the storm to our list
                    Storm s = new Storm(single);
                    storms.Add(s);

                    buf.Remove(0, buf.Length);
                }

                // Reading a Single Storm Entry, keep going
                if (state == 1 && line.Length > 0)
                    buf.AppendLine(line.Trim());
            }

            // return our list of parsed Storms
            return storms;
        }

        public List<ICoordinate> TrackHistory
        {
            get { return _trackHistory; }
            set { _trackHistory = value; }
        }

        public DateTime DateTime
        {
            get { return _dateTime; }
            set { _dateTime = value; }
        }
        List<Observation> _BAMD;

        public List<Observation> BAMD
        {
            get { return _BAMD; }
            set { _BAMD = value; }
        }
        List<Observation> _BAMM;

        public List<Observation> BAMM
        {
            get { return _BAMM; }
            set { _BAMM = value; }
        }
        List<Observation> _A98E;

        public List<Observation> A98E
        {
            get { return _A98E; }
            set { _A98E = value; }
        }
        List<Observation> _LBAR;

        public List<Observation> LBAR
        {
            get { return _LBAR; }
            set { _LBAR = value; }
        }
        List<int> _SHIP;

        public List<int> SHIP
        {
            get { return _SHIP; }
            set { _SHIP = value; }
        }
        List<int> _DSHP;

        public List<int> DSHP
        {
            get { return _DSHP; }
            set { _DSHP = value; }
        }

        public static void Update(Storm oldStorm, Storm newStorm)
        {
            oldStorm.TrackHistory.Add(new TrackHistoryPoint(new Point(AltitudeMode.clampToGround, oldStorm.Initial.Lat, oldStorm.Initial.Lon, 0), oldStorm.DateTime));
            oldStorm.A98E = newStorm.A98E;
            oldStorm.BAMD = newStorm.BAMD;
            oldStorm.BAMM = newStorm.BAMM;
            oldStorm.DateTime = newStorm.DateTime;
            oldStorm.Description = newStorm.Description;
            oldStorm.DSHP = newStorm.DSHP;
            oldStorm.ID = newStorm.ID;
            oldStorm.Initial = newStorm.Initial;
            oldStorm.LBAR = newStorm.LBAR;
            oldStorm.Name = newStorm.Name;
            oldStorm.SHIP = newStorm.SHIP;
        }

        public bool AddDiscussion(NHCDiscussion disc)
        {
            lock (this._nhcDiscussions)
            {
                if (this._nhcDiscussions == null)
                    this._nhcDiscussions = new List<NHCDiscussion>();
                foreach (NHCDiscussion d in this._nhcDiscussions)
                {
                    if (d.DateTime.Equals(disc.DateTime))
                    {
                        return false;
                    }
                }
                try
                {
                    this._nhcDiscussions.Add(disc);
                    this._nhcDiscussions.Sort();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    return false;
                }
            }

            return true;
        }

        public string Name
        {
            get { return this._name; }
            set { this._name = value; }
        }

        public string Description
        {
            get { return this._desc; }
            set { this._desc = value; }
        }

        public Observation Initial
        {
            get { return this._initial; }
            set { this._initial = value; }
        }

        public String ID
        {
            get { return this._stormID; }
            set { this._stormID = value; }
        }

        public void WriteTo(XmlTextWriter tw)
        {
            string desc = "";
            string tmp = "";
            tw.WriteStartElement("Folder");//storm
            tw.WriteElementString("name", this._name + " " + this._stormID);
            int y = 0;
            DateTime dt = DateTime.UtcNow;
            TimeSpan ts = new TimeSpan(12, 0, 0);

            #region Models
            tw.WriteStartElement("Folder");//model
            //tw.WriteElementString("visibility", "1");
            tw.WriteElementString("name", "Models");

            #region Initial
            tmp = "<pre>";
            tmp += this._dateTime.ToString() + " UTC\n";
            tmp += this._dateTime.ToLocalTime().ToString() + " EDT\n";
            tmp += "\n" + this._desc;
            tmp += "</pre>";
            Placemark intl = new Placemark(this._stormID + " " + this._name, tmp, "#Initial", "", true, this._initial.Location);
            intl.WriteTo(tw);
            #endregion

            #region TrackHistory
            if (this._trackHistory != null && this._trackHistory.Count > 0)
            {
                tw.WriteStartElement("Folder");//model
                tw.WriteElementString("name", "TrackHistory");
                tw.WriteElementString("Snippet", " ");

                #region Line
                List<ICoordinate> hist = this._trackHistory;
                hist.Add(this._initial.Location);
                LineString thls = new LineString(AltitudeMode.clampToGround, hist, false, true);
                Placemark th = new Placemark("TrackHistoryLine", "", "#Hist", "", true, thls);
                th.WriteTo(tw);
                #endregion

                #region Points
                foreach (ICoordinate o in this._trackHistory)
                {
                    if (o != null)
                    {
                        Placemark pm = new Placemark("", "", "#Hist", "", true, new Point(AltitudeMode.clampToGround, o.Lat, o.Lon, 0));
                        pm.WriteTo(tw);
                    }
                }

                #endregion

                tw.WriteEndElement();//trackHistory folder
            }
            #endregion

            List<ICoordinate> crds;

            #region BAMD
            if (this._BAMD.Count > 0)
            {
                tw.WriteStartElement("Folder");//model
                tw.WriteElementString("name", "BAMD");
                //tw.WriteElementString("visibility", "1");
                tw.WriteElementString("Snippet", "");

                #region Line
                crds = new List<ICoordinate>();
                foreach (Observation o in this._BAMD)
                {
                    if (o.Lat != 0 && o.Lon != 0)
                        crds.Add(o.Location);
                }
                LineString bamdLine = new LineString(AltitudeMode.clampToGround, crds, false, true);
                Placemark bamdPM = new Placemark("TrackLine", "", "#BAMD", "", true, bamdLine);
                bamdPM.WriteTo(tw);
                #endregion

                #region Points
                dt = this._dateTime;
                foreach (Observation o in this._BAMD)
                {
                    dt += ts;
                    if (o.Lat != 0 && o.Lon != 0)
                    {
                        desc = "<pre>";
                        desc += "BAMD\n\n";
                        desc += dt.ToString() + " UTC\n";
                        desc += dt.ToLocalTime().ToString() + " EDT\n\n";
                        desc += "Lat: " + o.Lat.ToString() + " Lon: " + o.Lon.ToString() + "\n";
                        desc += "SHIP: " + o.SHIP.ToString() + "kts\n";
                        desc += "DSHP: " + o.DSHP.ToString() + "kts\n";
                        desc += "</pre>";
                        Placemark pm = new Placemark(o.Hour + "hrs", desc, "#BAMD", "", true, o.Location);
                        pm.WriteTo(tw);
                    }
                }

                #endregion

                tw.WriteEndElement();//model folder
            }
            #endregion

            #region BAMM
            if (this._BAMM.Count > 0)
            {
                tw.WriteStartElement("Folder");//model
                tw.WriteElementString("name", "BAMM");
                //tw.WriteElementString("visibility", "1");
                tw.WriteElementString("Snippet", "");

                #region Line
                crds = new List<ICoordinate>();
                foreach (Observation o in this._BAMM)
                {
                    if (o.Lat != 0 && o.Lon != 0)
                        crds.Add(o.Location);
                }
                LineString bammLine = new LineString(AltitudeMode.clampToGround, crds, false, true);
                Placemark bammPM = new Placemark("TrackLine", "", "#BAMM", "", true, bammLine);
                bammPM.WriteTo(tw);
                #endregion

                #region Points
                dt = this._dateTime;
                foreach (Observation o in this._BAMM)
                {
                    dt += ts;
                    if (o.Lat != 0 && o.Lon != 0)
                    {
                        desc = "<pre>";
                        desc += "BAMM\n\n";
                        desc += dt.ToString() + " UTC\n";
                        desc += dt.ToLocalTime().ToString() + " EDT\n\n";
                        desc += "Lat: " + o.Lat.ToString() + " Lon: " + o.Lon.ToString() + "\n";
                        desc += "SHIP: " + o.SHIP.ToString() + "kts\n";
                        desc += "DSHP: " + o.DSHP.ToString() + "kts\n";
                        desc += "</pre>";
                        Placemark pm = new Placemark(o.Hour + "hrs", desc, "#BAMM", "", true, o.Location);
                        pm.WriteTo(tw);
                    }
                }

                #endregion

                tw.WriteEndElement();//model folder
            }
            #endregion

            #region LBAR
            if (this._LBAR.Count > 0)
            {
                tw.WriteStartElement("Folder");//model
                tw.WriteElementString("name", "LBAR");
                //tw.WriteElementString("visibility", "1");
                tw.WriteElementString("Snippet", "");

                #region Line
                crds = new List<ICoordinate>();
                foreach (Observation o in this._LBAR)
                {
                    if (o.Lat != 0 && o.Lon != 0)
                        crds.Add(o.Location);
                }
                LineString lbarLine = new LineString(AltitudeMode.clampToGround, crds, false, true);
                Placemark lbarPM = new Placemark("TrackLine", "", "#LBAR", "", true, lbarLine);
                lbarPM.WriteTo(tw);
                #endregion

                #region Points
                dt = this._dateTime;
                foreach (Observation o in this._LBAR)
                {
                    dt += ts;
                    if (o.Lat != 0 && o.Lon != 0)
                    {
                        desc = "<pre>";
                        desc += "LBAR\n\n";
                        desc += dt.ToString() + " UTC\n";
                        desc += dt.ToLocalTime().ToString() + " EDT\n\n";
                        desc += "Lat: " + o.Lat.ToString() + " Lon: " + o.Lon.ToString() + "\n";
                        desc += "SHIP: " + o.SHIP.ToString() + "kts\n";
                        desc += "DSHP: " + o.DSHP.ToString() + "kts\n";
                        desc += "</pre>";
                        Placemark pm = new Placemark(o.Hour + "hrs", desc, "#LBAR", "", true, o.Location);
                        pm.WriteTo(tw);
                    }
                }

                #endregion

                tw.WriteEndElement();//model folder
            }
            #endregion

            #region A98E
            if (this._A98E.Count > 0)
            {
                tw.WriteStartElement("Folder");//model
                tw.WriteElementString("name", "A98E");
                //tw.WriteElementString("visibility", "1");
                tw.WriteElementString("Snippet", "");

                #region Line
                crds = new List<ICoordinate>();
                foreach (Observation o in this._A98E)
                {
                    if (o.Lat != 0 && o.Lon != 0)
                        crds.Add(o.Location);
                }
                LineString a98eLine = new LineString(AltitudeMode.clampToGround, crds, false, true);
                Placemark a98ePM = new Placemark("TrackLine", "", "#A98E", "", true, a98eLine);
                a98ePM.WriteTo(tw);
                #endregion

                #region Points
                dt = this._dateTime;
                foreach (Observation o in this._A98E)
                {
                    dt += ts;
                    if (o.Lat != 0 && o.Lon != 0)
                    {
                        desc = "<pre>";
                        desc += "A98E\n\n";
                        desc += dt.ToString() + " UTC\n";
                        desc += dt.ToLocalTime().ToString() + " EDT\n\n";
                        desc += "Lat: " + o.Lat.ToString() + " Lon: " + o.Lon.ToString() + "\n";
                        desc += "SHIP: " + o.SHIP.ToString() + "kts\n";
                        desc += "DSHP: " + o.DSHP.ToString() + "kts\n";
                        desc += "</pre>";
                        Placemark pm = new Placemark(o.Hour + "hrs", desc, "#A98E", "", true, o.Location);
                        pm.WriteTo(tw);
                    }
                }

                #endregion

                tw.WriteEndElement();//model folder
            }
            #endregion

            tw.WriteEndElement();//models
            #endregion

            #region NHC Discussions
            if (this._nhcDiscussions.Count > 0)
            {
                tw.WriteStartElement("Folder");//model
                tw.WriteElementString("name", "NHC Discussions");
                tw.WriteElementString("Snippet", "");
                KmlWriter.WriteListStyle(ListItemType.radioFolder, tw);

                int cnt = 1;
                foreach (NHCDiscussion d in this._nhcDiscussions)
                {
                    #region Folder Start
                    tw.WriteStartElement("Folder");//model
                    if (cnt == 1)
                    {
                        tw.WriteElementString("name", "Most Recent NHC Discussion");
                        tw.WriteElementString("Snippet", "");
                        tw.WriteElementString("visibility", "0");
                    }
                    else
                    {
                        tw.WriteElementString("name", "NHC Discussion " + d.DateTime.ToString());
                        tw.WriteElementString("Snippet", "");
                        tw.WriteElementString("visibility", "0");
                    }
                    #endregion

                    #region Line
                    crds = new List<ICoordinate>();
                    foreach (Observation o in d.Forecast)
                        crds.Add(o.Location);
                    LineString discLine = new LineString(AltitudeMode.clampToGround, crds, false, true);
                    Placemark discPM = new Placemark("Discussion Track Line", "", "#NHC", "", false, discLine);
                    discPM.WriteTo(tw);
                    #endregion

                    #region Points
                    int ptCnt = 1;
                    DateTime init = d.DateTime;
                    foreach (Observation o in d.Forecast)
                    {
                        desc = "<pre>";
                        if (ptCnt == 1)
                            desc += d.EntireDiscussion;
                        else
                        {
                            if (ptCnt <= 5)
                            {
                                init += new TimeSpan(12, 0, 0);
                            }
                            else
                            {
                                init += new TimeSpan(24, 0, 0);
                            }
                            desc += "NHC Discussion Forecast Point\n\n";
                            desc += init.ToString() + " UTC\n";
                            desc += init.ToLocalTime().ToString() + " EDT\n\n";
                            desc += "Lat: " + o.Lat.ToString() + " Lon: " + o.Lon.ToString() + "\n";
                            desc += "SHIP: " + o.SHIP.ToString() + "kts\n";
                            desc += "DSHP: " + o.DSHP.ToString() + "kts\n";
                        }
                        desc += "</pre>";

                        Placemark pm = null;
                        if (ptCnt == 1)
                            pm = new Placemark("Initial Location", desc, "#NHC", "", false, o.Location);
                        else
                            pm = new Placemark(((TimeSpan)(init - d.DateTime)).TotalHours.ToString() + "hrs", desc, "#NHC", "", false, o.Location);
                        pm.WriteTo(tw);
                        ptCnt++;
                    }
                    #endregion

                    #region Folder End
                    tw.WriteEndElement(); // Current Disc Folder
                    #endregion

                    cnt++;
                }

                #region None
                KmlWriter.WriteEmpyFolderEntry("Discussions Off", true, tw);
                //tw.WriteStartElement("Folder");
                //tw.WriteElementString("name", "Discussions Off");
                //tw.WriteElementString("open", "0");
                ////tw.WriteElementString("visibility", "0");
                //tw.WriteEndElement();// no radars
                #endregion

                tw.WriteEndElement();//NHC Discussions Folder
            }
            #endregion

            #region Nearby Radars
            tw.WriteStartElement("Folder");
            if (_radars.Count > 0)
                tw.WriteElementString("name", "Nearby Radars");
            else
                tw.WriteElementString("name", "No Nearby Radars");
            tw.WriteElementString("open", "0");
            tw.WriteElementString("visibility", "0");
            KmlWriter.WriteListStyle(ListItemType.radioFolder, tw);

            if (_radars.Count > 0)
            {
                List<Radar> tmpRad = new List<Radar>();
                #region Long Range
                foreach (Radar r in this._radars)
                {
                    if (r.RadType == Radar.RadarType.LongReflect)
                        tmpRad.Add(r);
                }
                tw.WriteStartElement("Folder");
                tw.WriteElementString("visibility", "0");
                if (tmpRad.Count > 0)
                {
                    tw.WriteElementString("name", "Long Range Radar");
                }
                else
                {
                    tw.WriteElementString("name", "No Long Range Radar");
                }
                foreach (Radar r in tmpRad)
                {
                    Icon icon = new Icon(r.ImgLink, RefreshMode.onInterval, 300, 0, 0, 0, 0);
                    LatLonBox box = new LatLonBox(r.North, r.South, r.East, r.West, 0);
                    GroundOverlay radOv = new GroundOverlay(icon, box, null, r.Description, "ffffffff", 0, false);
                    radOv.WriteTo(tw);
                    //tw.WriteStartElement("GroundOverlay");
                    //tw.WriteElementString("visibility", "0");
                    //tw.WriteElementString("name", r.Description);
                    //tw.WriteStartElement("Icon");
                    //tw.WriteElementString("href", r.ImgLink);
                    //tw.WriteElementString("refreshMode", "onInterval");
                    //tw.WriteElementString("refreshInterval", "300");
                    //tw.WriteElementString("viewBoundScale", "0.75");
                    //tw.WriteEndElement(); // Icon
                    //tw.WriteStartElement("LatLonBox");
                    //tw.WriteElementString("north", r.North.ToString());
                    //tw.WriteElementString("south", r.South.ToString());
                    //tw.WriteElementString("east", r.East.ToString());
                    //tw.WriteElementString("west", r.West.ToString());
                    //tw.WriteEndElement(); // LatLonBox
                    //tw.WriteEndElement(); // Ground Overlay
                }
                tw.WriteEndElement();//Long range
                #endregion

                #region Composite
                tmpRad.Clear();
                foreach (Radar r in this._radars)
                {
                    if (r.RadType == Radar.RadarType.CompositeReflect)
                        tmpRad.Add(r);
                }
                tw.WriteStartElement("Folder");
                if (tmpRad.Count > 0)
                {
                    tw.WriteElementString("name", "Composite Radar");
                }
                else
                {
                    tw.WriteElementString("name", "No Composite Radar");
                }
                foreach (Radar r in tmpRad)
                {
                    Icon icon = new Icon(r.ImgLink, RefreshMode.onInterval, 300, 0, 0, 0, 0);
                    LatLonBox box = new LatLonBox(r.North, r.South, r.East, r.West, 0);
                    GroundOverlay radOv = new GroundOverlay(icon, box, null, r.Description, "ffffffff", 0, false);
                    radOv.WriteTo(tw);
                    //tw.WriteStartElement("GroundOverlay");
                    //tw.WriteElementString("visibility", "0");
                    //tw.WriteElementString("name", r.Description);
                    //tw.WriteStartElement("Icon");
                    //tw.WriteElementString("href", r.ImgLink);
                    //tw.WriteElementString("refreshMode", "onInterval");
                    //tw.WriteElementString("refreshInterval", "300");
                    //tw.WriteElementString("viewBoundScale", "0.75");
                    //tw.WriteEndElement(); // Icon
                    //tw.WriteStartElement("LatLonBox");
                    //tw.WriteElementString("north", r.North.ToString());
                    //tw.WriteElementString("south", r.South.ToString());
                    //tw.WriteElementString("east", r.East.ToString());
                    //tw.WriteElementString("west", r.West.ToString());
                    //tw.WriteEndElement(); // LatLonBox
                    //tw.WriteEndElement(); // Ground Overlay
                }
                tw.WriteEndElement();//Long range
                #endregion

                #region None
                KmlWriter.WriteEmpyFolderEntry("Radar Off", true, tw);
                //tw.WriteStartElement("Folder");
                //tw.WriteElementString("name", "Radar Off");
                //tw.WriteElementString("open", "0");
                ////tw.WriteElementString("visibility", "1");
                //tw.WriteEndElement();// no radars
                #endregion
            }

            tw.WriteEndElement();//Nearby Radars


            #endregion

            #region Nearby Buoys

            tw.WriteStartElement("Folder");//model
            //tw.WriteElementString("visibility", "1");
            tw.WriteElementString("open", "0");
            if (this._buoys != null && this._buoys.Count > 0)
            {
                tw.WriteElementString("name", "Nearby Buoys");
            }
            else
            {
                tw.WriteElementString("name", "No Nearby Buoys");
            }

            foreach (Buoy b in this._buoys.Values)
            {
                //tw.WriteStartElement("Folder");//
                //tw.WriteElementString("visibility", "1");
                //tw.WriteElementString("name", b.Id);
                //KmlWriter.WriteListStyle(ListItemType.checkHideChildren, tw);

                tmp = "";
                //tmp += "<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"15\">";
                tmp += "<img src=\"";
                tmp += "buoyImages/" + b.LocalFileName + "\"";
                //tmp += this._buoyImgHref + "/" + b.Id + ".png\"";
                tmp += "alt =\"Image for " + b.Id + " temporarily unavailable.\"";
                tmp += "><br>";

                tmp += "<a href=\"";
                tmp += b.InfoUrl;
                tmp += "\">More Info for " + b.Id + "</a>";
                Placemark pm = new Placemark(b.Id, tmp, "#Buoy", "", true, b.Location);
                pm.WriteTo(tw);

                //OverlayXY oxy = new OverlayXY(ScreenUnits.fraction, 0, 1);
                //ScreenXY sxy = new ScreenXY(ScreenUnits.fraction, 0, 1);
                //Size size = new Size(ScreenUnits.fraction, 0, 0);
                //ScreenOverlay so = new ScreenOverlay(b.Id, "", false, b.ImgUrl, sxy, oxy, size, RefreshMode.onInterval, 300);
                //so.WriteTo(tw);

                //tw.WriteEndElement();//
            }

            tw.WriteEndElement();//buoys folder

            #endregion

            tw.WriteEndElement();//Folder
        }
        #endregion

        #region Constructors
        public Storm(string s)
        {
            // Initialize Track History
            this._trackHistory = new List<ICoordinate>();

            //Initialize NHC Discussions
            this._nhcDiscussions = new List<NHCDiscussion>();

            this._BAMD = new List<Observation>();
            this._BAMM = new List<Observation>();
            this._A98E = new List<Observation>();
            this._LBAR = new List<Observation>();
            this._SHIP = new List<int>();
            this._DSHP = new List<int>();

            Category c = this.Parse(s);
            
            if (this._BAMM.Count > 0)
                this._initial = (Observation)this._BAMM[0];
            else if (this._BAMD.Count > 0)
                this._initial = (Observation)this._BAMD[0];
            else if (this._LBAR.Count > 0)
                this._initial = (Observation)this._LBAR[0];
            else if (this._A98E.Count > 0)
                this._initial = (Observation)this._A98E[0];
            else
                this._initial = new Observation("0", "0");
            
            // Set Category
            this._initial.Cat = c;
            this._initial.DateTime = this._dateTime;
        }
        #endregion

        #region Private Helpers

        private Category Parse(string s)
        {
            Category c = Category.TD;
            StringReader r = new StringReader(s);
            string line = "";
            while (line != null && (line = r.ReadLine()) != null)
            {
                // Name etc.
                if (line.Contains("(AL"))
                {
                    this._name = this.GetName(line);
                    this._stormID = this.GetID(line);
                    this._dateTime = this.GetDateTime(line);
                }

                if (line.Contains("BAMD"))
                {
                    this.ParseBAMD(line);
                }

                if (line.Contains("BAMM"))
                {
                    this.ParseBAMM(line);
                }

                if (line.Contains("A98E"))
                {
                    this.ParseA98E(line);
                }

                if (line.Contains("LBAR"))
                {
                    this.ParseLBAR(line);
                }

                if (line.Contains("SHIP"))
                {
                    this.ParseSHIP(line);
                }

                if (line.Contains("DSHP"))
                {
                    this.ParseDSHP(line);
                }

                if (line.Contains("INITIAL CONDITIONS"))
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine(line);
                    while ((line = r.ReadLine()) != null)
                    {
                        sb.AppendLine(line);
                    }
                    this._desc = sb.ToString();
                }
            }
            return c;
        }

        private string GetName(string s)
        {
            string name = "";
            string [] toks = s.Split(new char[] { ' ' });

            int index = 0;
            int tmp = 0;
            foreach (string ss in toks)
            {
                if (ss.Contains("(AL"))
                    index = tmp;
                tmp++;
            }
            tmp = 0;
            while (tmp < index)
            {
                if(toks[tmp].Length > 0)
                    name += toks[tmp] + " ";
                tmp++;
            }
            name = name.Trim();
            return name;
        }

        private string GetID(string s)
        {
            string id = "";
            string[] toks = s.Split(new char[] { ' ' });

            int index = 0;
            int tmp = 0;
            foreach (string ss in toks)
            {
                if (ss.Contains("(AL"))
                    index = tmp;
                tmp++;
            }

            id = toks[index];
            return id.Trim();
        }

        private DateTime GetDateTime(string s)
        {
            string date = "";
            string time = "";
            string[] toks = s.Split(new char[] { ' ' });
            ArrayList al = new ArrayList();
            foreach (string ss in toks)
            {
                if (ss.Length > 0)
                    al.Add(ss);
            }
            int index = 0;
            foreach (string sss in al)
            {
                if (sss.Contains("ON") && sss.Length <= 2)
                {
                    date = (string)al[index + 1];
                    time = (string)al[index + 2];
                    break;
                }
                index++;
            }
            int year = int.Parse(date.Substring(0, 4));
            int month = int.Parse(date.Substring(4, 2));
            int day = int.Parse(date.Substring(6, 2));
            int hr = int.Parse(time)/100;

            DateTime ret = new DateTime(year, month, day, hr, 0, 0, DateTimeKind.Utc);
            return ret;
        }

        private void ParseBAMD(string s)
        {
            string[] toks = s.Split(new char[] { ' ' });
            ArrayList al = new ArrayList();
            foreach (string ss in toks)
            {
                if (ss.Length > 0 && !ss.Contains("BAMD"))
                    al.Add(ss);
            }

            int index = 0;
            while(index <= al.Count-2)
            {
                string lat = (string)al[index];
                string lon = (string)al[index + 1];
                Observation o = new Observation(lat, lon, this.hrs[this._BAMD.Count]);
                this._BAMD.Add(o);
                index+=2;
            }
        }

        private void ParseBAMM(string s)
        {
            string[] toks = s.Split(new char[] { ' ' });
            ArrayList al = new ArrayList();
            foreach (string ss in toks)
            {
                if (ss.Length > 0 && !ss.Contains("BAMM"))
                    al.Add(ss);
            }

            int index = 0;
            while (index <= al.Count - 2)
            {
                string lat = (string)al[index];
                string lon = (string)al[index + 1];
                Observation o = new Observation(lat, lon, this.hrs[this._BAMM.Count]);
                this._BAMM.Add(o);
                index += 2;
            }
        }

        private void ParseA98E(string s)
        {
            string[] toks = s.Split(new char[] { ' ' });
            ArrayList al = new ArrayList();
            foreach (string ss in toks)
            {
                if (ss.Length > 0 && !ss.Contains("A98E"))
                    al.Add(ss);
            }

            int index = 0;
            while (index <= al.Count - 2)
            {
                string lat = (string)al[index];
                string lon = (string)al[index + 1];
                Observation o = new Observation(lat, lon, this.hrs[this._A98E.Count]);
                this._A98E.Add(o);
                index += 2;
            }
        }

        private void ParseLBAR(string s)
        {
            string[] toks = s.Split(new char[] { ' ' });
            ArrayList al = new ArrayList();
            foreach (string ss in toks)
            {
                if (ss.Length > 0 && !ss.Contains("LBAR"))
                    al.Add(ss);
            }

            int index = 0;
            while (index <= al.Count - 2)
            {
                string lat = (string)al[index];
                string lon = (string)al[index + 1];
                Observation o = new Observation(lat, lon, this.hrs[this.LBAR.Count]);
                this._LBAR.Add(o);
                index += 2;
            }
        }

        private void ParseSHIP(string s)
        {
            string[] toks = s.Split(new char[] { ' ' });
            ArrayList al = new ArrayList();
            foreach (string ss in toks)
            {
                if (ss.Length > 0 && ss.Contains("KTS"))
                {
                    int index = ss.IndexOf("KTS");
                    string tmp = ss.Substring(0, index);
                    this._SHIP.Add(int.Parse(tmp));
                }
            }

            foreach(int i in _SHIP)
            //if (this._SHIP.Count == 8)
            {
                int index = 0;
                foreach (Observation o in this._BAMD)
                {
                    o.SHIP = this._SHIP[index];//int.Parse((this._SHIP[index]).Substring(0,((this._SHIP[index]).Length-3));
                    index++;
                }
                index = 0;
                foreach (Observation o in this._BAMM)
                {
                    o.SHIP = this._SHIP[index];//int.Parse(((string)this._SHIP[index]).Substring(0, ((string)this._SHIP[index]).Length - 3));
                    index++;
                }
                index = 0;
                foreach (Observation o in this._A98E)
                {
                    o.SHIP = this._SHIP[index];//int.Parse(((string)this._SHIP[index]).Substring(0, ((string)this._SHIP[index]).Length - 3));
                    index++;
                }
                index = 0;
                foreach (Observation o in this._LBAR)
                {
                    o.SHIP = this._SHIP[index];//int.Parse(((string)this._SHIP[index]).Substring(0, ((string)this._SHIP[index]).Length - 3));
                    index++;
                }
            }
        }

        private void ParseDSHP(string s)
        {
            string[] toks = s.Split(new char[] { ' ' });
            ArrayList al = new ArrayList();
            foreach (string ss in toks)
            {
                if (ss.Length > 0 && ss.Contains("KTS"))
                {
                    int index = ss.IndexOf("KTS");
                    string tmp = ss.Substring(0, index);
                    this._DSHP.Add(int.Parse(tmp));
                }
            }

            foreach(int i in _SHIP)
            //if (this._DSHP.Count == 8)
            {
                int index = 0;
                foreach (Observation o in this._BAMD)
                {
                    o.DSHP = this._DSHP[index];//int.Parse(((string)this._DSHP[index]).Substring(0, ((string)this._DSHP[index]).Length - 3));
                    index++;
                }
                index = 0;
                foreach (Observation o in this._BAMM)
                {
                    o.DSHP = this._DSHP[index];//int.Parse(((string)this._DSHP[index]).Substring(0, ((string)this._DSHP[index]).Length - 3));
                    index++;
                }
                index = 0;
                foreach (Observation o in this._A98E)
                {
                    o.DSHP = this._DSHP[index];//int.Parse(((string)this._DSHP[index]).Substring(0, ((string)this._DSHP[index]).Length - 3));
                    index++;
                }
                index = 0;
                foreach (Observation o in this._LBAR)
                {
                    o.DSHP = this._DSHP[index];//int.Parse(((string)this._DSHP[index]).Substring(0, ((string)this._DSHP[index]).Length - 3));
                    index++;
                }
            }
        }

        private Category GetCategory(int speed)
        {
            if (speed < 34)
                return Category.TD;
            else if (speed < 64)
                return Category.TS;
            else if (speed < 82)
                return Category.Cat1;
            else if (speed < 95)
                return Category.Cat2;
            else if (speed < 113)
                return Category.Cat3;
            else if (speed < 135)
                return Category.Cat4;
            else
                return Category.Cat5;

        }
        #endregion
    }
}
